{$R-}

(*
	recvString(port number, termination character, waitTime, echo, edit,oldString) -- Return a string from the
		serial port; return everything available, up to the termination character (if any). Pass an empty
		termination character to receive everything available. WaitTime is the amount of time to wait
		for the input, in ticks (60ths of a second). Echo is true to enable echoing. Edit is true to enable edit
		characters (i.e., backspace). oldString is what was read the last call (presumably terminated
		due to a time-out).

	By Harry Chesley.  DO NOT call the author!  Contact Apple Developer 
	Support on AppleLink "MacDTS" or on MCI "MacTech".

	ŠApple Computer, Inc. 1987
	All Rights Reserved.

	To compile and link this file using Macintosh Programmer's Workshop,

	pascal -w recvString.p
	link -m ENTRYPOINT -o HyperCommands -rt XFCN=0 -sn Main=recvUpTo recvString.p.o "{MPW}"Libraries:interface.o
	
*)

{$S recvString } 	{ Segment name must be the same as the command name. }

unit DummyUnit;

interface

uses MemTypes, QuickDraw, OSIntf, ToolIntf, HyperXCmd;

procedure EntryPoint(paramPtr: XCmdPtr);
	
implementation

const

return = chr(13);
linefeed = chr(10);
bs = chr(8);

type

Str31 = String[31];

procedure recvString(paramPtr: XCmdPtr); forward;

procedure EntryPoint(paramPtr: XCmdPtr);

	begin
		recvString(paramPtr);
	end;

procedure recvString(paramPtr: XCmdPtr);

	var portNumber: integer;
		inPort, outPort: integer;
		str: Str255;
		l: longInt;
		waitForChars: longInt;
		lookForTerm: boolean;
		termChar: char;
		echoOn: boolean;
		editOn: boolean;
		linefeedStr: string[1];
		bsStr: string[3];
		resultHand: Handle;
		resultSize: longInt;
		theChar: char;
		p: Ptr;

	{$I XCmdGlue.inc}

	procedure Fail(errMsg: Str255); { set theResult and quit }
		begin
			paramPtr^.returnValue := PasToZero(errMsg);
			exit(recvString);
		end;

	begin
		if paramPtr^.paramCount <> 6 then Fail('parameter count is not 6');

		ZeroToPas(paramPtr^.params[1]^,str);		{ First parameter is port number. }
		portNumber := StrToNum(str);
		if (portNumber < 1) or (portNumber > 2) then Fail('invalid port number');
		ZeroToPas(paramPtr^.params[2]^,str);		{ Second parameter is termination character. }
		if length(str) = 0 then lookForTerm := false
		else
			begin
				lookForTerm := true;
				termChar := str[1];
			end;
		ZeroToPas(paramPtr^.params[3]^,str);		{ Third parameter is whether to wait. }
		waitForChars := StrToNum(str);
		ZeroToPas(paramPtr^.params[4]^,str);		{ Fourth parameter is whether to echo. }
		echoOn := false;
		if length(str) > 0 then
			if (str[1] = 't') or (str[1] = 'T') then echoOn := true;
		ZeroToPas(paramPtr^.params[5]^,str);		{ Fifth parameter is whether to edit. }
		editOn := false;
		if length(str) > 0 then
			if (str[1] = 't') or (str[1] = 'T') then editOn := true;
		resultHand := paramPtr^.params[6];			{ Sixth parameter is the old string. }
		if resultHand = NIL then Fail('NIL resultHandle!');
		l := GetHandleSize(resultHand);
		p := resultHand^;
		resultSize := 1;
		while resultSize < l do
			begin
				if p^ = 0 then leave;
				p := Ptr(ord4(p)+1);
				resultSize := resultSize + 1;
			end;
		if resultSize < 1 then Fail('Input string size too small!');
		if HandToHand(resultHand) <> noErr then Fail('HandToHand failed!');
		resultSize := resultSize-1;
		SetHandleSize(resultHand,resultSize);

		if portNumber = 1 then
			begin
				inPort := -6;
				outPort := -7;
			end
		else
			begin
				inPort := -8;
				outPort := -9;
			end;
		linefeedStr[0] := chr(1); linefeedStr[1] := linefeed;
		bsStr := '   '; bsStr[1] := bs; bsStr[3] := bs;
		waitForChars := waitForChars + TickCount;
		while TickCount <= waitForChars do
			begin
				if SerGetBuf(inPort,l) <> noErr then
					begin
						DisposHandle(resultHand);
						Fail('SerGetBuf failed');
					end;
				if l = 0 then cycle;
				l := 1;
				resultSize := resultSize+1;
				SetHandleSize(resultHand,resultSize);
				if MemError <> noErr then
					begin
						DisposHandle(resultHand);
						Fail('SetHandleSize failed!');
					end;
				HLock(resultHand);
				if FSRead(inPort,l,Ptr(ord4(resultHand^)+resultSize-1)) <> noErr then
					begin
						DisposHandle(resultHand);
						Fail('FSRead failed');
					end;
				HUnlock(resultHand);
				p := Ptr(ord4(resultHand^)+resultSize-1);
				p^ := BAND(p^,$7F);
				theChar := chr(p^);
				if echoOn then
					begin
						l := 1;
						if FSWrite(outPort,l,Ptr(ord4(resultHand^)+resultSize-1)) <> noErr then
							Fail('FSWriter failed');
						if theChar = return then
							begin
								l := length(linefeedStr);
								if FSWrite(outPort,l,Ptr(ord4(@linefeedStr)+1)) <> noErr then Fail('FSWrite failed');
							end;
						if editOn and (theChar = bs) then
							begin
								l := length(bsStr);
								if FSWrite(outPort,l,Ptr(ord4(@bsStr)+1)) <> noErr then Fail('FSWrite failed');
							end;
					end;
				if editOn then
					begin
						if theChar = bs then
							begin
								resultSize := resultSize-2;
								if resultSize < 0 then resultSize := 0;
								SetHandleSize(resultHand,resultSize);
							end;
					end;
				if lookForTerm then
					if theChar = termChar then leave;
				if resultSize > 30000 then leave;
			end;
		SetHandleSize(resultHand,resultSize+1);
		p := ptr(ord4(resultHand^)+resultSize);
		p^ := 0;
		paramPtr^.returnValue := resultHand;
	end;

end.
